<template>
    <view class="u-tooltip" :style="[$u.addStyle(customStyle)]">
        <view class="u-tooltip__wrapper">
            <!-- <text
				class="u-tooltip__wrapper__text"
				:id="textId"
				:ref="textId"
				:userSelect="false"
				:selectable="false"
				@longpress.stop="longpressHandler"
				:style="{
					color: color,
					backgroundColor: bgColor && showTooltip && tooltipTop !== -10000 ? bgColor : 'transparent'
				}"
			>{{ text }}</text> -->
            <view :id="textId" :ref="textId" :userSelect="false" :selectable="false">
                <slot>
                    <text
                        class="u-tooltip__wrapper__text"
                        :userSelect="false"
                        :selectable="false"
                        @longpress.stop="longpressHandler"
                        :style="{
                            color: color,
                            backgroundColor: bgColor && showTooltip && tooltipTop !== -10000 ? bgColor : 'transparent'
                        }"
                    >
                        {{ text }}
                    </text>
                </slot>
            </view>
            <view v-if="showTooltip" :style="[tooltipStyle]">
                <view class="u-tooltip__wrapper__popup" :id="tooltipId" :ref="tooltipId">
                    <view
                        class="u-tooltip__wrapper__popup__indicator"
                        hover-class="u-tooltip__wrapper__popup__indicator--hover"
                        v-if="showCopy || buttons.length"
                        :style="[
                            indicatorStyle,
                            {
                                width: $u.addUnit(indicatorWidth),
                                height: $u.addUnit(indicatorWidth)
                            }
                        ]"
                    >
                        <!-- 由于nvue不支持三角形绘制，这里就做一个四方形，再旋转45deg，得到露出的一个三角 -->
                    </view>
                    <view class="u-tooltip__wrapper__popup__list">
                        <view v-if="showCopy" class="u-tooltip__wrapper__popup__list__btn" hover-class="u-tooltip__wrapper__popup__list__btn--hover" @tap="setClipboardData">
                            <text class="u-tooltip__wrapper__popup__list__btn__text">复制</text>
                        </view>
                        <u-line direction="column" color="#8d8e90" v-if="showCopy && buttons.length > 0" length="18"></u-line>
                        <block v-for="(item, index) in buttons" :key="index">
                            <view class="u-tooltip__wrapper__popup__list__btn" hover-class="u-tooltip__wrapper__popup__list__btn--hover">
                                <text class="u-tooltip__wrapper__popup__list__btn__text" @tap="btnClickHandler(index)">{{ item }}</text>
                            </view>
                            <u-line direction="column" color="#8d8e90" v-if="index < buttons.length - 1" length="18"></u-line>
                        </block>
                    </view>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
import props from './props'
import mixin from '../../libs/mixin/mixin'
/**
 * Tooltip
 * @description
 * @tutorial https://ijry.github.io/uview-plus/components/tooltip.html
 * @property {String | Number}	text		需要显示的提示文字
 * @property {String | Number}	copyText	点击复制按钮时，复制的文本，为空则使用text值
 * @property {String | Number}	size		文本大小（默认 14 ）
 * @property {String}			color		字体颜色（默认 '#606266' ）
 * @property {String}			bgColor		弹出提示框时，文本的背景色（默认 'transparent' ）
 * @property {String}			direction	弹出提示的方向，top-上方，bottom-下方（默认 'top' ）
 * @property {String | Number}	zIndex		弹出提示的z-index，nvue无效（默认 10071 ）
 * @property {Boolean}			showCopy	是否显示复制按钮（默认 true ）
 * @property {Array}			buttons		扩展的按钮组
 * @property {Boolean}			overlay		是否显示透明遮罩以防止触摸穿透（默认 true ）
 * @property {Object}			customStyle	定义需要用到的外部样式
 *
 * @event {Function}
 * @example
 */
export default {
    name: 'u-tooltip',
    mixins: [mixin, props],
    data() {
        return {
            // 是否展示气泡
            showTooltip: true,
            // 生成唯一id，防止一个页面多个组件，造成干扰
            textId: uni.$u.guid(),
            tooltipId: uni.$u.guid(),
            // 初始时甚至为很大的值，让其移到屏幕外面，为了计算元素的尺寸
            tooltipTop: -10000,
            // 气泡的位置信息
            tooltipInfo: {
                width: 0,
                left: 0
            },
            // 文本的位置信息
            textInfo: {
                width: 0,
                left: 0
            },
            // 三角形指示器的样式
            indicatorStyle: {},
            // 气泡在可能超出屏幕边沿范围时，重新定位后，距离屏幕边沿的距离
            screenGap: 12,
            // 三角形指示器的宽高，由于对元素进行了角度旋转，精确计算指示器位置时，需要用到其尺寸信息
            indicatorWidth: 14
        }
    },
    watch: {
        propsChange() {
            this.getElRect()
        }
    },
    computed: {
        // 特别处理H5的复制，因为H5浏览器是自带系统复制功能的，在H5环境
        // 当一些依赖参数变化时，需要重新计算气泡和指示器的位置信息
        propsChange() {
            return [this.text, this.buttons]
        },
        // 计算气泡和指示器的位置信息
        tooltipStyle() {
            const style = {
                    position: 'absolute',
                    top: this.$u.addUnit(this.tooltipTop),
                    zIndex: this.zIndex,
                    transform: `translateY(${this.direction === 'top' ? '-100%' : '100%'})`
                },
                sysInfo = this.$u.sys()
            if (this.tooltipInfo.width / 2 > this.textInfo.left + this.textInfo.width / 2 - this.screenGap) {
                this.indicatorStyle = {}
                style.left = `-${this.$u.addUnit(this.textInfo.left - this.screenGap)}`
                this.indicatorStyle.left = this.$u.addUnit(this.textInfo.width / 2 - this.$u.getPx(style.left) - this.indicatorWidth / 2)
            } else if (this.tooltipInfo.width / 2 > sysInfo.windowWidth - this.textInfo.right + this.textInfo.width / 2 - this.screenGap) {
                this.indicatorStyle = {}
                style.right = `-${this.$u.addUnit(sysInfo.windowWidth - this.textInfo.right - this.screenGap)}`
                this.indicatorStyle.right = this.$u.addUnit(this.textInfo.width / 2 - this.$u.getPx(style.right) - this.indicatorWidth / 2)
            } else {
                const left = Math.abs(this.textInfo.width / 2 - this.tooltipInfo.width / 2)
                style.left = this.textInfo.width > this.tooltipInfo.width ? this.$u.addUnit(left) : -this.$u.addUnit(left)
                this.indicatorStyle = {}
            }
            if (this.direction === 'top') {
                style.marginTop = '-10px'
                this.indicatorStyle.bottom = '-4px'
            } else {
                style.marginBottom = '-10px'
                this.indicatorStyle.top = '-4px'
            }
            return style
        }
    },
    mounted() {
        this.init()
    },
    emits: ['click'],
    methods: {
        init() {
            this.getElRect()
        },
        // 长按触发事件
        async longpressHandler() {
            this.tooltipTop = 0
            this.showTooltip = true
        },
        // 点击透明遮罩
        overlayClickHandler() {
            this.showTooltip = false
        },
        // 点击弹出按钮
        btnClickHandler(index) {
            this.showTooltip = false
            // 如果需要展示复制按钮，此处index需要加1，因为复制按钮在第一个位置
            this.$emit('click', this.showCopy ? index + 1 : index)
        },
        // 查询内容高度
        queryRect(ref) {
            // #ifndef APP-NVUE
            // $uGetRect为uView自带的节点查询简化方法，详见文档介绍：https://ijry.github.io/uview-plus/js/getRect.html
            // 组件内部一般用this.$uGetRect，对外的为uni.$u.getRect，二者功能一致，名称不同
            return new Promise(resolve => {
                this.$uGetRect(`#${ref}`).then(size => {
                    resolve(size)
                })
            })
            // #endif
        },
        // 元素尺寸
        getElRect() {
            // 调用之前，先将指示器调整到屏幕外，方便获取尺寸
            this.showTooltip = true
            this.tooltipTop = -10000
            setTimeout(() => {
                this.queryRect(this.tooltipId).then(size => {
                    this.tooltipInfo = size
                    // 获取气泡尺寸之后，将其隐藏，为了让下次切换气泡显示与隐藏时，有淡入淡出的效果
                    this.showTooltip = false
                })
                this.queryRect(this.textId).then(size => {
                    this.textInfo = size
                })
            }, 500)
        },
        // 复制文本到粘贴板
        setClipboardData() {
            // 关闭组件
            this.showTooltip = false
            this.$emit('click', 0)
            uni.setClipboardData({
                // 优先使用copyText字段，如果没有，则默认使用text字段当做复制的内容
                data: this.copyText || this.text,
                success: () => {
                    this.showToast && this.$u.toast('复制成功')
                },
                fail: () => {
                    this.showToast && this.$u.toast('复制失败')
                },
                complete: () => {
                    this.showTooltip = false
                }
            })
        }
    }
}
</script>

<style lang="scss" scoped>
@import '../../libs/css/mixin.scss';
.u-tooltip {
    position: relative;
    @include flex;

    &__wrapper {
        @include flex;
        justify-content: center;
        /* #ifndef APP-NVUE */
        white-space: nowrap;
        /* #endif */

        &__text {
            font-size: 14px;
        }

        &__popup {
            @include flex;
            justify-content: center;

            &__list {
                background-color: #060607;
                position: relative;
                flex: 1;
                border-radius: 5px;
                padding: 0px 0;
                @include flex(row);
                align-items: center;
                overflow: hidden;

                &__btn {
                    padding: 6px 13px;

                    &--hover {
                        background-color: #58595b;
                    }

                    &__text {
                        line-height: 12px;
                        font-size: 13px;
                        color: #ffffff;
                    }
                }
            }

            &__indicator {
                position: absolute;
                background-color: #060607;
                width: 14px;
                height: 14px;
                bottom: -4px;
                transform: rotate(45deg);
                border-radius: 2px;
                z-index: -1;

                &--hover {
                    background-color: #58595b;
                }
            }
        }
    }
}
</style>
